package manager

import (
	"BlazeRider-backend/app/db"
	"database/sql"
	"fmt"
	"log"
	"strings"
	"sync"
)

// DouYinFailGiftRecordMysqlStorage 管理抖音推送失败的礼物赠送记录
type DouYinFailGiftRecordMysqlInfo struct {
	MsgId      string       `db:"msg_id"`
	LiveRoomId string       `db:"live_room_id"`
	PageNum    int          `db:"page_num"`
	Times      int          `db:"times"`
	UserId     string       `db:"user_id"`
	GiftId     string       `db:"gift_id"`
	Amount     int          `db:"amount"`
	OneValue   int          `db:"one_value"`
	TotalValue int          `db:"total_value"`
	Status     string       `db:"status"`
	CreateAt   sql.NullTime `db:"create_at"` // 使用 NullTime
	UpdateAt   sql.NullTime `db:"update_at"` // 使用 NullTime
}

// DouYinFailGiftRecordMysqlStorage 管理抖音推送失败的礼物赠送记录
type DouYinFailGiftMaxPageInfo struct {
	LiveRoomId string `db:"live_room_id"`
	MaxPageNum int    `db:"max_page_num"`
	Count      int    `db:"count"`
}

type DouYinFailGiftRecordMysqlStorage struct {
	roomGiftRecords map[string]map[string][]DouYinFailGiftRecord
	db              *sql.DB
	mu              sync.Mutex
}

func NewDouYinFailGiftRecordMysqlStorage() (*DouYinFailGiftRecordMysqlStorage, error) {
	return &DouYinFailGiftRecordMysqlStorage{
		roomGiftRecords: make(map[string]map[string][]DouYinFailGiftRecord),
	}, nil
}

// AddGiftRecord 增加礼物赠送记录
func (grm *DouYinFailGiftRecordMysqlStorage) GetGiftRecordByMsgId(msgID string) (*DouYinFailGiftRecordMysqlInfo, error) {
	// 定义一个变量来存储查询结果
	var giftRecordMysqlInfo DouYinFailGiftRecordMysqlInfo

	// 执行 SQL 查询
	err := db.GetDB().QueryRow(`
        SELECT msg_id, live_room_id, times, user_id, gift_id, amount, one_value, total_value, create_at, update_at
        FROM douyin_fail_gift_records
        WHERE msg_id = ?
		Limit 1
    `, msgID).Scan(
		&giftRecordMysqlInfo.MsgId,
		&giftRecordMysqlInfo.LiveRoomId,
		&giftRecordMysqlInfo.Times,
		&giftRecordMysqlInfo.UserId,
		&giftRecordMysqlInfo.GiftId,
		&giftRecordMysqlInfo.Amount,
		&giftRecordMysqlInfo.OneValue,
		&giftRecordMysqlInfo.TotalValue,
		&giftRecordMysqlInfo.CreateAt,
		&giftRecordMysqlInfo.UpdateAt,
	)

	// 处理错误
	if err != nil {
		if err == sql.ErrNoRows {
			log.Printf("No live room found by msgId: %s", msgID)
			return nil, err // 没有找到数据，返回 ErrNoRows
		}
		log.Printf("Error querying get gift record by msgId: %v", err) // 打印其他错误信息
		return nil, err                                                // 返回其他错误
	}

	// 查询成功，返回结果
	return &giftRecordMysqlInfo, nil
}

// AddGiftRecordsBatch 批量增加礼物赠送记录
func (grm *DouYinFailGiftRecordMysqlStorage) AddGiftRecordsBatch(records []DouYinFailGiftRecordMysqlInfo) error {
	// 定义单批次最大插入量
	const batchSize = 100
	total := len(records)

	// 获取数据库连接
	db := db.GetDB()

	// 开启事务
	tx, err := db.Begin()
	if err != nil {
		return fmt.Errorf("开启事务失败: %v", err)
	}

	// 循环处理批次
	for i := 0; i < total; i += batchSize {
		end := i + batchSize
		if end > total {
			end = total
		}

		batch := records[i:end]
		// 将结构体切片转换为指针切片
		ptrBatch := make([]*DouYinFailGiftRecordMysqlInfo, len(batch))
		for j := range batch {
			ptrBatch[j] = &batch[j]
		}
		if err := insertBatch(tx, ptrBatch); err != nil {
			_ = tx.Rollback()
			return err
		}
	}

	// 提交事务
	if err := tx.Commit(); err != nil {
		return fmt.Errorf("提交事务失败: %v", err)
	}
	return nil
}

// 单批次插入
func insertBatch(tx *sql.Tx, records []*DouYinFailGiftRecordMysqlInfo) error {
	// 构建基础SQL
	baseSQL := `
        INSERT INTO douyin_fail_gift_records 
            (msg_id, live_room_id, page_num, times, user_id, gift_id, 
            amount, one_value, total_value, status,
            create_at, update_at)
        VALUES
    `

	// 生成占位符和参数
	placeholders := make([]string, 0, len(records))
	args := make([]interface{}, 0, len(records)*14)

	for _, r := range records {
		placeholders = append(placeholders, "(?, ?, ?, ?, ?, ?, ?, ?, ?, 'pre', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)")

		// 按字段顺序填充参数
		args = append(args,
			r.MsgId,             // 1. msg_id
			r.LiveRoomId,        // 2. live_room_id
			r.PageNum,           // 3. page_num
			r.Times,             // 4. times
			r.UserId,            // 5. user_id
			r.GiftId,            // 6. gift_id
			r.Amount,            // 7. amount
			r.OneValue,          // 8. one_value
			r.OneValue*r.Amount, // 9. total_value
		)
	}

	// 组合完整SQL
	fullSQL := baseSQL + strings.Join(placeholders, ",")

	// 执行批量插入
	if _, err := tx.Exec(fullSQL, args...); err != nil {
		return fmt.Errorf("批量插入失败: %v\nSQL: %s", err, fullSQL)
	}
	return nil
}

// 查询本局最后一次该礼物信息
func (grm *DouYinFailGiftRecordMysqlStorage) GetLastPageNumAndCountByLiveRoomId(liveRoomID string) (*DouYinFailGiftMaxPageInfo, error) {
	// 定义一个变量来存储查询结果
	var douYinFailGiftMaxPageInfo DouYinFailGiftMaxPageInfo

	// 执行 SQL 查询
	err := db.GetDB().QueryRow(`
        SELECT MAX(page_num) AS max_page_num 
        FROM douyin_fail_gift_records
        WHERE live_room_id = ? 
    `, liveRoomID).Scan(
		&douYinFailGiftMaxPageInfo.MaxPageNum,
	)

	// 处理错误
	if err != nil {
		if err == sql.ErrNoRows {
			log.Printf("No live room found in GetLastPageNumAndCountByLiveRoomId 1 with ID: %s", liveRoomID)
			return nil, err // 没有找到数据，返回 ErrNoRows
		}
		log.Printf("Error querying GetLastPageNumAndCountByLiveRoomId 1 : %v", err) // 打印其他错误信息
		return nil, err                                                             // 返回其他错误
	}

	// 执行 SQL 查询
	err = db.GetDB().QueryRow(`
        SELECT COUNT(1) AS num 
        FROM douyin_fail_gift_records
        WHERE live_room_id = ? and
              page_num = ?
		ORDER BY create_at DESC
    `, liveRoomID, douYinFailGiftMaxPageInfo.MaxPageNum).Scan(
		&douYinFailGiftMaxPageInfo.Count,
	)

	// 处理错误
	if err != nil {
		if err == sql.ErrNoRows {
			log.Printf("No live room in GetLastPageNumAndCountByLiveRoomId 2 found with ID: %s", liveRoomID)
			return nil, err // 没有找到数据，返回 ErrNoRows
		}
		log.Printf("Error querying in GetLastPageNumAndCountByLiveRoomId 2 live room: %v", err) // 打印其他错误信息
		return nil, err                                                                         // 返回其他错误
	}

	douYinFailGiftMaxPageInfo.LiveRoomId = liveRoomID

	// 查询成功，返回结果
	return &douYinFailGiftMaxPageInfo, nil
}

// 根据传入的msgId数组，返回数据库中已存在的msgId列表
func (grm *DouYinFailGiftRecordMysqlStorage) FilterExistingMsgIds(msgIDs []string) ([]string, error) {
	// 边界检查：空数组直接返回
	if len(msgIDs) == 0 {
		return []string{}, nil
	}

	// 构建SQL查询参数
	placeholders := strings.Repeat("?,", len(msgIDs)-1) + "?"
	args := make([]interface{}, len(msgIDs))
	for i, id := range msgIDs {
		args[i] = id
	}

	// 执行查询
	rows, err := db.GetDB().Query(`
    SELECT msg_id 
    FROM douyin_fail_gift_records 
    WHERE msg_id IN (`+placeholders+`)
  `, args...)

	if err != nil {
		log.Printf("Query error: %v", err)
		return nil, err
	}
	defer rows.Close()

	// 收集存在的msgId
	existingIDs := make([]string, 0)
	for rows.Next() {
		var msgID string
		if err := rows.Scan(&msgID); err != nil {
			log.Printf("Scan error: %v", err)
			return nil, err
		}
		existingIDs = append(existingIDs, msgID)
	}

	// 检查遍历过程中的错误
	if err := rows.Err(); err != nil {
		log.Printf("Row iteration error: %v", err)
		return nil, err
	}

	return existingIDs, nil
}

func (grm *DouYinFailGiftRecordMysqlStorage) SetFailGiftDoneOrFail(msgId string, status, reason string) error {
	_, err := db.GetDB().Exec(`
		update douyin_fail_gift_records
		set status = ?,
			reason = ?,
			update_at = CURRENT_TIMESTAMP
		where
		    msg_id = ?
	`,
		status, reason, msgId) // 更新值参数

	if err != nil {
		return fmt.Errorf("set Fail Gift Done Or Fail error: %v", err)
	}
	return nil
}
